package cn.mdmbct.douyin.common.proxy;

import cn.mdmbct.douyin.common.executor.ServiceExecutor;
import cn.mdmbct.douyin.common.http.HttpExecutor;
import cn.mdmbct.douyin.common.session.DySession;
import lombok.Getter;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

/**
 * 抖音open API service 仓库接口 <br>
 * 仅用作标记哪些类存放调用抖音open API的service的 <br>
 * 单例的
 *
 * @author mdmbct  mdmbct@outlook.com
 * @date 5/5/2021 10:19 AM
 * @modified mdmbct
 * @since 1.0
 */
public class ServiceRepository implements Serializable {

    private static final long serialVersionUID = -6023686764055975493L;

    @Getter
    private final Map<Class<?>, ServiceProxyFactory<?>> knownServices;

    private final ServiceExecutor serviceExecutor;

    public ServiceRepository(DySession dySession, HttpExecutor httpExecutor) {
        this.knownServices = new HashMap<>();
        this.serviceExecutor = new ServiceExecutor(dySession, httpExecutor);
    }


    public void addServiceInterface(Class<?> clazz) {

        if (hasService(clazz)) {
            throw new BindingException("DyService " + clazz + " is already known to the ServiceRepository.");
        }
        knownServices.put(clazz, new ServiceProxyFactory<>(clazz));
    }

    public void addServiceInterfaces(String... packageNames) {

        ServiceLoader loader = new ServiceLoader(this);
        loader.loadServiceInterfaces(packageNames);
    }

    public void addServiceInterfaces(ServicePath... servicePaths) {
        for (ServicePath servicePath : servicePaths) {
            addServiceInterfaces(servicePath.serviceInterfacesPackage());
        }
    }


    public boolean hasService(Class<?> clazz) {
        return knownServices.containsKey(clazz);
    }

    @SuppressWarnings("unchecked")
    public <T> T getDyService(Class<T> clazz) {
        ServiceProxyFactory<T> factory = (ServiceProxyFactory<T>) knownServices.get(clazz);
        if (factory == null) {
            throw new BindingException("DyService " + clazz + " is not known to the MapperRegistry.");
        }

        return factory.create(serviceExecutor);

    }




}
